{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Connection Examples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to a default Redis instance, running locally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "\n",
    "connection = redis.Redis()\n",
    "connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### by default Redis return binary responses, to decode them use decode_responses=True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "\n",
    "decoded_connection = redis.Redis(decode_responses=True)\n",
    "decoded_connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to a redis instance, specifying a host and port with credentials."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "\n",
    "user_connection = redis.Redis(host='localhost', port=6380, username='dvora', password='redis', decode_responses=True)\n",
    "user_connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Connecting to a redis instance with username and password credential provider"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import redis\n",
    "\n",
    "creds_provider = redis.UsernamePasswordCredentialProvider(\"username\", \"password\")\n",
    "user_connection = redis.Redis(host=\"localhost\", port=6379, credential_provider=creds_provider)\n",
    "user_connection.ping()"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Connecting to a redis instance with standard credential provider"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from typing import Tuple\n",
    "import redis\n",
    "\n",
    "creds_map = {\"user_1\": \"pass_1\",\n",
    "             \"user_2\": \"pass_2\"}\n",
    "\n",
    "class UserMapCredentialProvider(redis.CredentialProvider):\n",
    "    def __init__(self, username: str):\n",
    "        self.username = username\n",
    "\n",
    "    def get_credentials(self) -> Tuple[str, str]:\n",
    "        return self.username, creds_map.get(self.username)\n",
    "\n",
    "# Create a default connection to set the ACL user\n",
    "default_connection = redis.Redis(host=\"localhost\", port=6379)\n",
    "default_connection.acl_setuser(\n",
    "    \"user_1\",\n",
    "    enabled=True,\n",
    "    passwords=[\"+\" + \"pass_1\"],\n",
    "    keys=\"~*\",\n",
    "    commands=[\"+ping\", \"+command\", \"+info\", \"+select\", \"+flushdb\"],\n",
    ")\n",
    "\n",
    "# Create a UserMapCredentialProvider instance for user_1\n",
    "creds_provider = UserMapCredentialProvider(\"user_1\")\n",
    "# Initiate user connection with the credential provider\n",
    "user_connection = redis.Redis(host=\"localhost\", port=6379,\n",
    "                              credential_provider=creds_provider)\n",
    "user_connection.ping()"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Connecting to a redis instance first with an initial credential set and then calling the credential provider"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from typing import Union\n",
    "import redis\n",
    "\n",
    "class InitCredsSetCredentialProvider(redis.CredentialProvider):\n",
    "    def __init__(self, username, password):\n",
    "        self.username = username\n",
    "        self.password = password\n",
    "        self.call_supplier = False\n",
    "\n",
    "    def call_external_supplier(self) -> Union[Tuple[str], Tuple[str, str]]:\n",
    "        # Call to an external credential supplier\n",
    "        raise NotImplementedError\n",
    "\n",
    "    def get_credentials(self) -> Union[Tuple[str], Tuple[str, str]]:\n",
    "        if self.call_supplier:\n",
    "            return self.call_external_supplier()\n",
    "        # Use the init set only for the first time\n",
    "        self.call_supplier = True\n",
    "        return self.username, self.password\n",
    "\n",
    "cred_provider = InitCredsSetCredentialProvider(username=\"init_user\", password=\"init_pass\")"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Connecting to a redis instance with AWS Secrets Manager credential provider."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import redis\n",
    "import boto3\n",
    "import json\n",
    "import cachetools.func\n",
    "\n",
    "sm_client = boto3.client('secretsmanager')\n",
    "  \n",
    "def sm_auth_provider(self, secret_id, version_id=None, version_stage='AWSCURRENT'):\n",
    "    @cachetools.func.ttl_cache(maxsize=128, ttl=24 * 60 * 60) #24h\n",
    "    def get_sm_user_credentials(secret_id, version_id, version_stage):\n",
    "        secret = sm_client.get_secret_value(secret_id, version_id)\n",
    "        return json.loads(secret['SecretString'])\n",
    "    creds = get_sm_user_credentials(secret_id, version_id, version_stage)\n",
    "    return creds['username'], creds['password']\n",
    "\n",
    "secret_id = \"EXAMPLE1-90ab-cdef-fedc-ba987SECRET1\"\n",
    "creds_provider = redis.CredentialProvider(supplier=sm_auth_provider, secret_id=secret_id)\n",
    "user_connection = redis.Redis(host=\"localhost\", port=6379, credential_provider=creds_provider)\n",
    "user_connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to a redis instance with ElastiCache IAM credential provider."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "import boto3\n",
    "import cachetools.func\n",
    "\n",
    "ec_client = boto3.client('elasticache')\n",
    "\n",
    "def iam_auth_provider(self, user, endpoint, port=6379, region=\"us-east-1\"):\n",
    "    @cachetools.func.ttl_cache(maxsize=128, ttl=15 * 60) # 15m\n",
    "    def get_iam_auth_token(user, endpoint, port, region):\n",
    "        return ec_client.generate_iam_auth_token(user, endpoint, port, region)\n",
    "    iam_auth_token = get_iam_auth_token(endpoint, port, user, region)\n",
    "    return iam_auth_token\n",
    "\n",
    "username = \"barshaul\"\n",
    "endpoint = \"test-001.use1.cache.amazonaws.com\"\n",
    "creds_provider = redis.CredentialProvider(supplier=iam_auth_provider, user=username,\n",
    "                                           endpoint=endpoint)\n",
    "user_connection = redis.Redis(host=endpoint, port=6379, credential_provider=creds_provider)\n",
    "user_connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to Redis instances by specifying a URL scheme.\n",
    "Parameters are passed to the following schems, as parameters to the url scheme.\n",
    "\n",
    "Three URL schemes are supported:\n",
    "\n",
    "- `redis://` creates a TCP socket connection. <https://www.iana.org/assignments/uri-schemes/prov/redis>\n",
    "- `rediss://` creates a SSL wrapped TCP socket connection. <https://www.iana.org/assignments/uri-schemes/prov/rediss>\n",
    "- ``unix://``: creates a Unix Domain Socket connection.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "url_connection = redis.from_url(\"redis://localhost:6379?decode_responses=True&health_check_interval=2\")\n",
    "\n",
    "url_connection.ping()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to a Sentinel instance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from redis.sentinel import Sentinel\n",
    "sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)\n",
    "sentinel.discover_master(\"redis-py-test\")"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "d45c99ba0feda92868abafa8257cbb4709c97f1a0b5dc62bbeebdf89d4fad7fe"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}